/*BOXD为接线盒数字型，由宫老师开发。
BOXD和DT45数字型之间通过RS485相连，协议为modbus-rtu，BOXD为主机，提供各种寄存器。
RS485为DT45D的USART3。
*/
#include <stdio.h>
#include <string.h>

#include "stm32l4xx.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_lpuart.h"
#include "stm32l4xx_ll_usart.h"

#include "..\bsp_uart_ble.h"		//没什么用处。
#include "..\bsp_modbus.h"
#include "..\bsp.h"
#include "bsp_dtu.h"
#include "..\parameter.h"
#include "..\threads.h"

#include "dbgUart.h"


extern uint8_t gps_recv_0D0A_en;
extern RFID rfid;

uint32_t flag_modbus_recv_dtu;


RECV_INFO recv_info_dtu={.tmo_max= 10, .sta= STA_DTU_R_CMD};


const uint32_t _tbl_baud_dtu[]={/*1200,4800,*/9600,19200,38400,57600,115200, 0};
const char* _tbl_fmt_ble[]={/*" 7-E-1", " 7-O-1",*/  FMT_8_n_2, FMT_8_O_1, FMT_8_E_1, FMT_8_n_1, NULL};


UART_CFG2 uart_to_dtu_cfg={115200, FMT_8_n_1, 0};



/*DTU所用复位引脚PA7。
上电复位时，PA7为Analog Input，表现为低电平。即未复位DTU模块。
*/
void bsp_rst_dtu_hal(void)
{	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_7,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);
	DTU_RST_VALID;			//!!上电默认输出H，即复位着DTU。	
}



/*设置RS485的串口模式，波特率和当前状态。
*/
void bsp_uart_dtu_config(const char* fmt, uint32_t baud, uint8_t sta)
{
	uint32_t pclk1_clock;
	uint32_t baud_rate;
	
	
	baud_rate= baud;

	if(baud_rate< 19200){	
		//使能HSI，并等待稳定。
		LL_RCC_HSI_Enable();
		while(0 == LL_RCC_HSI_IsReady()){}	//不能使用LL_RCC_IsActiveFlag_HSIRDY()。
			
		LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_HSI);
	}
	else{
		LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_SYSCLK);
	}
	
	pclk1_clock= LL_RCC_GetUSARTClockFreq(LL_RCC_USART3_CLKSOURCE);
	LL_USART_SetBaudRate(UART_DTU, pclk1_clock, 0, baud_rate);	//第3个参数是OverSampling。 QQ可以在USART使能时，更改波特率吗？

	

	LL_USART_Disable(UART_DTU);
		
	if(0){
	}
	else if(0 == strcmp(fmt, FMT_8_E_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_O_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_9B, LL_USART_PARITY_EVEN, LL_USART_STOPBITS_1);	//奇偶校验时，数据宽度须为9B。
	}
	else if(0 == strcmp(fmt, FMT_8_n_1)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	else if(0 == strcmp(fmt, FMT_8_n_2)){
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_2);
	}
	else{	//FMT_8_L_1...
		LL_USART_ConfigCharacter(UART_DTU, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
	}
	
	

	LL_USART_Enable(UART_DTU);
	

	
	//根据波特率，设定接收超时时间（暂统一）
	recv_info_dtu.tmo_max= 100;	//500ms
}



/*USART3的硬件：
PC4: USART3_TX
PC5: USART3_RX

*/
static void bsp_uart_dtu_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);

	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_4, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_4, LL_GPIO_AF_7);				//C AF7 as USART3_TX.
	
	LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_5, LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_5, LL_GPIO_MODE_ALTERNATE);
	LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_5, LL_GPIO_AF_7);				//C AF7 as USART3_RX.
}



/*配置MCU和BOXD盒相连的串口。
!!需要开启相应时钟。
!!115200用11520标示。
*/
void bsp_uart_dtu_init(uint32_t baud, const char* fmt)
{
	bsp_uart_dtu_hal();
	
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3);
	//LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_SYSCLK);		//PCLK as USART1's clock source,!!Must enable USART1_EN@RCC_APB1ENR1.
	
	LL_USART_Disable(UART_DTU);	//因为会动态修改该串口参数，所以假定它处于使能状态，需先禁止。
	
	
	/*配置串口：中断接收，查询发送。
	帧格式：
	0：无校验：2位停止位
	1：奇校验，1位停止位；
	2：偶校验，1位停止位；
	3：无校验，1位停止位；
	波特率：
	0  9600");
	1  19200");
	2  38400");
	3  57600");
	4  115200");
	*/
	uart_to_dtu_cfg.baud= baud;
	strcpy(uart_to_dtu_cfg.fmt, fmt);
	uart_to_dtu_cfg.sta= 0;
	
	//C OVER8@CR1=0, 16 samples.
	/* baudrate= fck/(8*(2-OVER8)*UARTDIV). UARTDIV= man.fra.
	例fpclk=84MHz，16samples，115200时，man.fra=45.5625，即0x2D9。
	具体参考RM0090's P978。
	*/
	bsp_uart_dtu_config(uart_to_dtu_cfg.fmt, uart_to_dtu_cfg.baud, 0);	//9600/19200/38400/57600

	
	LL_USART_EnableDirectionTx(UART_DTU);
	LL_USART_EnableDirectionRx(UART_DTU);
	
	LL_USART_SetRxTimeout(UART_DTU,40);		//40个bit duration.在使能USART前设置，好。 测试发现，设置为40后，都是488，不再出现“1，487”。
	LL_USART_Enable(UART_DTU);
	
	
//	#ifdef USE_USART_DMA_TXRX
//		//使能USART3的RTOF中断。
//		LL_USART_ClearFlag_RTO(UART_DTU);
//		LL_USART_ClearFlag_ORE(UART_DTU);
//		LL_USART_EnableIT_ERROR(UART_DTU);		//FE or ORE or NF @ISR为1时，就引起中断。
//		LL_USART_EnableIT_RTO(UART_DTU);		//硬件设置，软件清零（1->RTOCF）。
//		LL_USART_EnableRxTimeout(UART_DTU);
//		
//		DTU_UART_TX_DMA_init();
//		DTU_UART_RX_DMA_init();
//	
//	#else
//		LL_USART_EnableIT_RXNE(UART_DTU);
//	#endif
	
	/* preemption = 1, sub-priority = 1 */
	NVIC_SetPriority(UART_DTU_IRQn, 1);
	/* Enable Interrupt for UART channel */
	//NVIC_EnableIRQ(UART_DTU_IRQn);
}



/*USART3的RTO ISR，以
可以通过的内容，判断出是否为主动上报数据或AT响应。
*/
void UART_DTU_RTO_IRQHandler(void)
{
	char str[32];
	static uint32_t cnt_tot;
	
	uint32_t cnt_recv;
	
	if(LL_USART_IsActiveFlag_RTO(UART_DTU)){
		LL_USART_ClearFlag_RTO(UART_DTU);
		
		//uartS("*");
		//LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3);

		//判断是否有DMA接收数据。
		cnt_recv= 512- LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_3);
		cnt_tot+= cnt_recv;
		
		sprintf(str, "\n*=%d\ttot= %d", cnt_recv, cnt_tot); 
		uartS(str);
		
		//buf_idx此时指向空的。
		dtu_data.buf_dtu_to_mcu[cnt_recv]='\0';		//字符串结尾。
		strcpy((char*)dtu_data.buf[dtu_data.buf_idx], (char*)dtu_data.buf_dtu_to_mcu);
		
		uint8_t* p= &dtu_data.buf[dtu_data.buf_idx][0];
		
		osMessageQueuePut(mid_dtu_to_mcu, &p, 0, 0);
		
		if(0 == dtu_data.buf_idx)
			dtu_data.buf_idx= 1;
		else
			dtu_data.buf_idx= 0;
		
		
		//重新配置DMA（QQ配置流程：禁止--修改--使能）。
		if(cnt_recv != 0){
			//DMA已收到数据，需要重新复位。
			LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3);
			LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, 512);
			LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3);
			
			if(dbg_sw& DBG_DTU_DMA)
				uartS("\n+++");
		}
	}
	
	
	/**/
	if(LL_USART_IsActiveFlag_ORE(UART_DTU)){
		LL_USART_ClearFlag_ORE(UART_DTU);	
	}
}


/*DTU接收以"????usr.cn#??\r\n......\r\n?????"的数据包，其中的'?'是1个或无字符。
目前只处理一种情况：当收到usr.cn#后，进入接收"\r\n......\r\n"数据包，正好是$GNRMC。
>[Tx->][16:37:11][asc]
usr.cn#at+gpsdt

>[Rx<-][16:37:11][asc]
+GPSDT:
usr.cn#+GPSDT:
$GNRMC,,V,,,,,,,,,,N,V*37
$GNGGA,,,,,,0,00,99.9,,,,,,*6F
$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A
$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F
$GPGSV,1,1,00,0*65
$BDGSV,1,1,00,0*74

OK
*/
void UART_DTU_IRQHandler(void)
{
	uint8_t tmp8;
	uint32_t ts_del, ts_cur;
	static uint8_t buf_cmd[6];
	
	
	if(SET == LL_USART_IsActiveFlag_RXNE(UART_DTU)){
		tmp8= LL_USART_ReceiveData8(UART_DTU);
		
		if(0 == gps_recv_0D0A_en)	//已有数据，不能再保存，直接退出。
			return;
		
		ts_cur= ts_get();
		
		ts_del= ts_del_o_n(recv_info_dtu.ts, ts_cur);	//计算得到2个字符间的时间间隔。
		
		
		if(ts_del> recv_info_dtu.tmo_max){	//接收过程中，任何超过tmo_max(200ms)的间隔，状态都将从STA_IDLE开始。
			recv_info_dtu.sta= STA_DTU_R_CMD;	
			
			uartS("\nDTU tmo ");
		}
		
		recv_info_dtu.ts= ts_cur;
		
		
		
		/*接收状态机。
		*/
		switch (recv_info_dtu.sta){
			case STA_DTU_R_CMD:
				buf_cmd[0]= buf_cmd[1];
				buf_cmd[1]= buf_cmd[2];
				buf_cmd[2]= buf_cmd[3];
				buf_cmd[3]= buf_cmd[4];
				buf_cmd[4]= buf_cmd[5];
				buf_cmd[5]= tmp8;
			
				if( ('u' == buf_cmd[0]) &&
				    ('s' == buf_cmd[1]) &&
				    ('r' == buf_cmd[2]) &&
				    ('.' == buf_cmd[3]) &&
				    ('c' == buf_cmd[4]) &&
				    ('n' == buf_cmd[5]) ){
				
					recv_info_dtu.sta= STA_DTU_R_0D_S;

					if(dbg_sw & DBG_DTU_RECV){
						uartS("C");
					}						
				}
				else{
					if(dbg_sw & DBG_DTU_RECV){
						uartS("Y");
					}
				}
				break;
				
			case STA_DTU_R_0D_S:	//处于IDLE，准备接收地址码。
				if(tmp8 == '\r'){
					recv_info_dtu.sta= STA_DTU_R_0A_S;
					
					if(dbg_sw & DBG_DTU_RECV){
						uartS("R");
					}
				}
				else{
					if(dbg_sw & DBG_DTU_RECV){
						uartS("X");
					}	
				}
				break;
			
			case STA_DTU_R_0A_S:	
				if(tmp8 == '\n'){
				
					recv_info_dtu.sta= STA_DTU_R_DATA;
					recv_info_dtu.idx= 0;
					
					if(dbg_sw & DBG_DTU_RECV){
						uartS("N");
					}
				}
				
				break;
			
			case STA_DTU_R_DATA:	//接收\r\n之后的数据。
				recv_info_dtu.buf[recv_info_dtu.idx++]= tmp8;	//
				
				if(tmp8 == '\r')
					recv_info_dtu.sta= STA_DTU_R_0A_E;	
			
				if(dbg_sw & DBG_DTU_RECV){
					uartS("D");
				}
				break;
			
			case STA_DTU_R_0A_E:
				if(tmp8 == '\n'){
					recv_info_dtu.buf[recv_info_dtu.idx++]= tmp8;
					recv_info_dtu.buf[recv_info_dtu.idx++]= '\0';	//字符串结束。
					
					if(dbg_sw & DBG_DTU_RECV){
						uartS(">");
					}
					
					//已收到一个包"\r\n....\r\n"，发给Thread_Dtu()。
					osEventFlagsSet(evt_id_dtu_recv, 0x00000001U);
				}
				else{
					//错误	
				}
				
				recv_info_dtu.sta= STA_DTU_R_CMD;		//准备接收下一个。
				break;			
	
			default:
				break;
		}	
	}
	else if(SET == LL_USART_IsActiveFlag_ORE(UART_DTU)){	//错误处理
		//清除标志的方法：先读状态寄存器，再读数据寄存器，则自动清零USART_INT_FLAG_RBNE_ORERR。---错。
		//主动清除。
		tmp8= LL_USART_ReceiveData8(UART_DTU);
		LL_USART_ClearFlag_ORE(UART_DTU);
		uartS("*");
	}
}



///*向读卡器发送指令后，读卡器以<LF>Rxxxxxxxxxxxxxx<CR><LF>格式发送应答。
//38400,8-n-1。
//通过厂家软件读取的EPC是：96bits。
//发送:<LF>R1,2,6,<CR>（十六进制：0A 52 31 2C 32 2C 36 0D.
//接收:<LF>E2806995000060040761693E<CR><LR>
//*/
//void UART_RFID_IRQHandler(void)
//{
//	uint8_t tmp8;
//	uint32_t ts_del, ts_cur;
//	static uint8_t buf_cmd[6];
//	
//	
//	if(SET == LL_USART_IsActiveFlag_RXNE(UART_DTU)){
//		tmp8= LL_USART_ReceiveData8(UART_DTU);
//		
//		if(0 == rfid.recv_en)	//已有数据，不能再保存，直接退出。
//			return;
//		
//		ts_cur= ts_get();
//		
//		ts_del= ts_del_o_n(rfid.ts, ts_cur);	//计算得到2个字符间的时间间隔。
//		
//		
//		if(ts_del> rfid.tmo){	//接收过程中，任何超过tmo_max(200ms)的间隔，状态都将从STA_IDLE开始。
//			rfid.sta= STA_RFID_R_0A_S;	
//			
//			uartS("\nRFID tmo ");
//		}
//		
//		rfid.ts= ts_cur;
//		
//		
//		
//		/*接收状态机。
//		*/
//		switch (rfid.sta){
//			case STA_RFID_R_0A_S:
//				if('\n' == tmp8){
//					rfid.sta= STA_RFID_R_CMD;
//					
//					
//					if(dbg_sw & DBG_RFID){
//						
//						uartS("C");
//					}						
//				}
//				else{
//					//接收到的第1个字节不是<LF>。
//					if(dbg_sw & DBG_RFID){
//						uartS("X");
//					}
//				}
//				
//				break;

//			case STA_RFID_R_CMD:
//				if('R' == tmp8){
//					rfid.sta= STA_RFID_R_DATA;
//					rfid.id_idx= 0;
//					
//					if(dbg_sw & DBG_RFID){
//						uartS("R");
//					}						
//				}
//				else{
//					rfid.sta= STA_RFID_R_0A_S;
//					
//					//接收到的命令字节不是'R'。
//					if(dbg_sw & DBG_RFID){
//						uartS("X");
//					}
//				}
//				
//				break;
//			
//			case STA_RFID_R_DATA:	//处于IDLE，准备接收地址码。
//				if(tmp8 == '\r'){	//<CR>
//					rfid.sta= STA_RFID_R_0A_E;
//				}
//				else{
//					rfid.id_data[rfid.id_idx++]= tmp8;	//执行后，.idx为已接收个数。	
//				
//					if(dbg_sw & DBG_RFID){
//						uartS("D");
//					}
//				
//					if(32 <rfid.id_idx){
//						recv_info_dtu.sta= STA_RFID_R_0A_S;	//重新开始
//					
//						if(dbg_sw & DBG_RFID){
//							uartS("E");
//						}
//					}
//				}
//				
//				break;
//			
//			case STA_RFID_R_0A_E:	
//				if(tmp8 == '\n'){	//<LF> 已收到一整包。
//					
//					//flag_modbus_recv_ble= 1;	//数据保存在modbus_recv_info_ble.buf[]，长度为modbus_recv_info_ble.idx。
//					//osEventFlagsSet(evt_id_triger_read_rfid, 0x00000001U);
//					rfid.recv_ok= 1;	//接收完成。
//					
//					rfid.recv_en= 0;	//暂定接收。
//			
//					if(dbg_sw & DBG_RFID){
//						uartS("O");
//					}
//				}
//				else{
//					if(dbg_sw & DBG_RFID){
//						uartS("F");
//					}
//				}
//				
//				//收到的是否是<LF>，都要重置接收状态。
//				rfid.sta= STA_RFID_R_0A_S;
//				
//				break;
//			
//			
//			default:
//				break;
//		}	
//	}
//	else if(SET == LL_USART_IsActiveFlag_ORE(UART_DTU)){	//错误处理
//		//清除标志的方法：先读状态寄存器，再读数据寄存器，则自动清零USART_INT_FLAG_RBNE_ORERR。---错。
//		//主动清除。
//		tmp8= LL_USART_ReceiveData8(UART_DTU);
//		LL_USART_ClearFlag_ORE(UART_DTU);
//		uartS("*");
//	}
//}


/************************ END OF FILE ************************/

